package cn.tanglong.order.service.impl;

import cn.tanglong.basic.exception.MyException;
import cn.tanglong.basic.service.impl.BaseServiceImpl;
import cn.tanglong.basic.util.LoginContextUtil;
import cn.tanglong.order.domain.Order;
import cn.tanglong.order.domain.OrderAddress;
import cn.tanglong.order.domain.OrderPetDetail;
import cn.tanglong.order.dto.OrderDto;
import cn.tanglong.order.service.IOrderAddressService;
import cn.tanglong.order.service.IOrderPetDetailService;
import cn.tanglong.order.service.IOrderService;
import cn.tanglong.pay.dimain.PayBill;
import cn.tanglong.pay.service.IPayBillService;
import cn.tanglong.pet.domain.Pet;
import cn.tanglong.pet.service.IPetDetailService;
import cn.tanglong.pet.service.IPetService;
import cn.tanglong.quartz.job.OrderExpireJob;
import cn.tanglong.quartz.service.IQuartzService;
import cn.tanglong.user.domain.Logininfo;
import cn.tanglong.user.domain.UserAddress;
import cn.tanglong.user.mapper.UserAddressMapper;
import org.apache.commons.httpclient.util.DateUtil;
import org.apache.commons.lang3.time.DateUtils;
import org.assertj.core.util.diff.myers.MyersDiff;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

@Service
@Transactional
public class OrderServiceImpl extends BaseServiceImpl<Order> implements IOrderService {

    @Autowired
    private IPetService petService;

    @Autowired
    private UserAddressMapper userAddressMapper;

    @Autowired
    private IOrderPetDetailService orderPetDetailService;

    @Autowired
    private IOrderAddressService orderAddressService;

    @Autowired
    private IPayBillService payBillService;

    @Autowired
    private IQuartzService quartzService;

    /**
     * 下单流程:
     * 用户点击下单
     * 校验前端传过来的参数
     * 查询宠物信息和宠物状态，判断是否上架和有货
     * 查询用户信息、地址、支付方式等
     * 创建订单号，设置支付时间
     * 保存订单数据和订单明细
     * 库存减少（下单的时候就减少库存）
     * @param
     */
    @Override
    public String downOrder(OrderDto orderDto) {
        // 校验参数
        Long addressId = orderDto.getAddressId();
        Integer payType = orderDto.getPayType();
        Long petId = orderDto.getPetId();
        if (StringUtils.isEmpty(addressId)
                || StringUtils.isEmpty(payType)
                || StringUtils.isEmpty(petId)) {
            throw new MyException("请填入有效参数！");
        }
        // 查询宠物信息
        Pet pet = petService.selectOnLineById(petId);
        if (pet == null) {
            throw new MyException("暂时无货！");
        }
        // 查询用户的收获地址
        UserAddress userAddress = userAddressMapper.selectById(addressId);
        if (userAddress == null) {
            throw new MyException("请输入有效的地址！");
        }
        // 创建订单号 通过UUID生成一个随机订单号
        // replaceAll：因为UUID生成的中间有-号 所以替换成空
        String orderNu = UUID.randomUUID().toString().replaceAll("-", "");
        // 计算支付超时时间
        Date now = new Date();
        // 设置30分钟订单支付时间
        // 10秒测试
        Date overTime = DateUtils.addSeconds(now, 10);
        // 保存订单 把下单的所有参数都保存到order对象里去
        Order order = new Order();
        order.setDigest("确认购买: " + pet.getName());
        order.setCreateTime(now);
        order.setPayExpireTime(overTime);
        order.setOrderSn(orderNu);
        order.setPayType(payType);
        order.setState(Order.STATE_SUCCESS_PAY);
        order.setTotalCount(1);
        order.setTotalPrice(pet.getSaleprice().add(new BigDecimal("10")));
        Logininfo loginContext = LoginContextUtil.getLoginContext();
        if (loginContext == null) {
            throw new MyException("请登录");
        }
        order.setUserId(loginContext.getId());
        super.add(order);

        // 保存订单明细
        OrderPetDetail detail = new OrderPetDetail();
        detail.setName(pet.getName());
        detail.setResources(pet.getResources());
        // 注意 如果购买了多个 需要把多个订单的价格全部加起来
        detail.setPrice(pet.getSaleprice());
        detail.setCount(1);
        detail.setCreatetime(now);
        detail.setPetId(pet.getId());
        detail.setOrderId(order.getId());
        detail.setOrderSn(orderNu);
        detail.setShopId(pet.getShop().getId());
        detail.setShopName(pet.getShop().getName());
        // 保存详情表
        orderPetDetailService.add(detail);

        // 保存订单的地址
        OrderAddress address = new OrderAddress();
        // 把userAddress的数据拷贝给address
        BeanUtils.copyProperties(userAddress, address);
        address.setOrderId(order.getId());
        address.setOrderSn(orderNu);
        address.setCreateTime(now);

        // 保存到地址表
        orderAddressService.add(address);

        // 宠物表和库存减少
        // 若是只有一件货 但是两个人同时买就有问题 所以要上锁
        synchronized (this) {
            // 判断是否有货
            if (pet.getStore_number() == 0 || pet.getStore_number() == null) {
                throw new MyException("暂时无货！");
            }
            // 成功卖出。库存-1
            pet.setStore_number(pet.getStore_number() - 1);
        }
        // 保存修改到数据库
        petService.update(pet);

        // 保存支付单
        payBillService.save(
                order.getId(),   //外键
                PayBill.BUSINESS_TYPE_PET, //业务类型
                "购买：" + pet.getName() + "，支付：" + order.getTotalPrice(),
                order.getTotalPrice(), //总价格
                orderDto.getPayType(),//支付方式用户选的
                pet.getShop().getId(),//店铺
                pet.getShop().getName(),
                order.getOrderSn()); //单号

        Map<String, String> map = new HashMap<>();
        map.put("orderNU", orderNu);
        String jobName = "orderExpireJob"+orderNu;
        map.put("jobName", jobName);
        quartzService.addOrderExpireJob(
            "orderExpireJob"+orderNu, OrderExpireJob.class, "参数", overTime);

        //返回订单号
        return orderNu;
    }
}
